/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/08/17
*/
#include "Container.h"
#include "../edui.h"

EDUI_NAMESPACE_BEGIN

void Container::Release()
{
    this->Clear();
#ifdef EDUI_TEST_NEW_DELETE
    --m_newdeleteNum;
    Log("[Container] delete container : %s, %d", this->GetName(), this);
#endif
#ifdef EDUI_USE_LUAPLUS
    LuaMgrPtr->Remove(this);
#endif
    delete this;
}
Container* Container::GetInterface()
{
    Container* container = new Container;
#ifdef EDUI_TEST_NEW_DELETE
    ++m_newdeleteNum;
    Log("[Container] new container : %d", container);
#endif
#ifdef EDUI_USE_LUAPLUS
    LuaMgrPtr->Add("Container", container);
#endif
    return container;
}

Container* Container::ToContainer(Control* ctrl)
{
    return dynamic_cast<Container*>(ctrl);
}

Container::Container() : m_items(0), m_hScrollBar(0), m_vScrollBar(0)
{
    m_items = new ItemMap;
    Assert(m_items);
}

Container::~Container()
{
    if (m_items){
        delete m_items;
        m_items = 0;
    }

    if (m_vScrollBar){
        m_vScrollBar->Release();
        m_vScrollBar = 0;
    }

    if (m_hScrollBar){
        m_hScrollBar->Release();
        m_hScrollBar = 0;
    }
}

bool Container::Add(Control* ctrl)
{
    if (!ctrl->SetWindow(this->GetWindow()) || !ctrl->SetParent(this)){
        return false;
    }
    m_items->push_back(ctrl);
    return true;
}

bool Container::AddAt(Control* ctrl, size_t index)
{
    if (!ctrl->SetWindow(this->GetWindow())) return false;
    if (!ctrl->SetParent(this)) return false;

    if (index < 0) index = 0;
    if (index > m_items->size()) index = m_items->size();
    m_items->insert(m_items->begin() + index, ctrl);

    return true;
}

Control* Container::Get(const char* name)
{
    if (!name) return 0;
    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end();  ++it){
        if((*it) && strcmp((*it)->GetName(), name) == 0){
            return (*it);
        }
    }
    return 0;
}

Control* Container::GetByIndex(size_t index)
{
    if ( index < 0 || index >= m_items->size()) return 0;
    return m_items->at(index);
}

void Container::Remove(Control* ctrl)
{
    if (!ctrl) return;
    
    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end(); ++it){
        if((*it) && ((*it) == ctrl)){
            (*it)->Release();
            m_items->erase(it);
            return;
        }
    }
}

void Container::Remove(const char* name)
{
    if (!name) return;
    
    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end();  ++it){
        if((*it) && strcmp((*it)->GetName(), name) == 0){
            (*it)->Release();
            m_items->erase(it);
            return;
        }
    }
}

void Container::RemoveByIndex(size_t index)
{
    if ( index < 0 || index >= m_items->size()) return;

    ItemMap::iterator it = m_items->begin() + index;
    (*it)->Release();
    m_items->erase(it);
}

void Container::Clear()
{
    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end();  ++it){
        if (*it){
            (*it)->Release();
        }
    }
    m_items->clear();
}

size_t Container::Count()
{
    return m_items->size();
}

//-----------------------------//

ScrollBar* Container::GetHScrollBar()
{
    return m_hScrollBar;
}

ScrollBar* Container::GetVScrollBar()
{
    return m_vScrollBar;
}

bool Container::LoadHScrollBar(const char* xmlstr)
{
    if (!xmlstr) return false;

    if (!m_hScrollBar){
        m_hScrollBar = ScrollBar::ToScrollBar(IEnginePtr->GetControlInterface("ScrollBar"));
        if (!m_hScrollBar) return false;
    }

    if (!m_hScrollBar->IsOK()){
        m_hScrollBar->SetWindow(m_wnd);
    }

    return m_hScrollBar->LoadLayout(xmlstr);
}

bool Container::LoadVScrollBar(const char* xmlstr)
{
    if (!xmlstr) return false;

    if (!m_vScrollBar){
        m_vScrollBar = ScrollBar::ToScrollBar(IEnginePtr->GetControlInterface("ScrollBar"));
        if (!m_vScrollBar) return false;
    }

    if (!m_vScrollBar->IsOK()){
        m_vScrollBar->SetWindow(m_wnd);
    }

    return m_vScrollBar->LoadLayout(xmlstr);
}

//-----------------------------//
bool Container::HandleMsg(Msg* msg)
{
    ItemMap::reverse_iterator it;
    for (it = m_items->rbegin(); it != m_items->rend(); ++it){
        if ((*it) && (*it)->IsVisible() && (*it)->IsEnabled()){
            if ((*it)->HandleMsg(msg)){
                return true;
            }
        }
    }
    return Control::HandleMsg(msg);
}

void Container::Render(IRender* render, const Rect* rc)
{
    Rect oldclip = render->GetClip();

    if (rc) render->SetClip(rc);
    else render->SetClip(&m_rc);

    this->RenderBkColor(render, rc);
    this->RenderBkImages(render, rc);
    this->RenderStatusImages(render, rc);
    this->RenderForeImages(render, rc);
    this->RenderText(render, rc);
    this->RenderBorder(render, rc);

    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end(); ++it){
        if ((*it) && (*it)->IsVisible() && (*it)->NeedRender(rc)){
            (*it)->Render(render, rc);
        }
    }

    render->SetClip(&oldclip);
}

Control* Container::FindControl(const char* name)
{
    if (Control::FindControl(name)) return this;
    for (ItemMap::iterator it = m_items->begin(); it != m_items->end(); ++it){
        if (*it){
            Control* ctrl =(*it)->FindControl(name);
            if (ctrl) return ctrl;
        }
    }
    return 0;
}

Control* Container::FindControlByTabID(int id)
{
    if (Control::FindControlByTabID(id)) return this;
    for (ItemMap::iterator it = m_items->begin(); it != m_items->end(); ++it){
        if (*it){
            Control* ctrl =(*it)->FindControlByTabID(id);
            if (ctrl) return ctrl;
        }
    }
    return 0;
}

Control* Container::FindControlByPt(int x, int y, Uint32 flag)
{
    if (!Control::FindControlByPt(x, y, flag)) return 0;
    ItemMap::reverse_iterator it;
    for (it = m_items->rbegin(); it != m_items->rend(); ++it){
        if (*it){
            Control* ctrl =(*it)->FindControlByPt(x, y, flag);
            if (ctrl) return ctrl;
        }
    }
    return this;
}

bool Container::ChildCanInvaldate(Control* child)
{
    Container* parent = Container::ToContainer(this->GetParent());
    if (parent) return parent->ChildCanInvaldate(this);
    return true;
}

bool Container::SetInset(const Rect1* inset)
{
    if (!inset) return false;
    m_rcInset = *inset;
    return true;
}

Rect1 Container::GetInset() const
{
    return m_rcInset;
}

void Container::SetChildPadding(int paddingX, int paddingY)
{
    m_childPadding.w = paddingX;
    m_childPadding.h = paddingY;
}

Size Container::GetChildPadding() const
{
    return m_childPadding;
}

void Container::AutoLayout()
{
    if (m_wnd->GetRoot() == this){
        m_rc.Reset(0, 0, m_wnd->GetWidth(), m_wnd->GetHeight());
    }
    Control::AutoLayout();

    if (m_items->size() == 0) return;

    Rect rc = m_rc;
    rc.x += m_rcInset.l;
    rc.y += m_rcInset.t;
    rc.w -= (m_rcInset.l + m_rcInset.r);
    rc.h -= (m_rcInset.t + m_rcInset.b);

    ItemMap::iterator it;
    for (it = m_items->begin(); it != m_items->end(); ++it){
        if ((*it) && (*it)->IsVisible()){
            (*it)->SetRect(&rc);
            (*it)->AutoLayout();
        }
    }
}

void Container::SetAttribute(const char* name, const char* value)
{
    if (0 == strcmp(name, "inset")){
        Rect1 rc = ParserRect1(value);
        this->SetInset(&rc);
    } else if (0 == strcmp(name, "childpadding")){
        m_childPadding = ParserSize(value);
    } else if (0 == strcmp(name, "hscrollbar")){
        this->LoadHScrollBar(value);
    } else if (0 == strcmp(name, "vscrollbar")){
        this->LoadVScrollBar(value);
    } else {
        Control::SetAttribute(name, value);
    }
}

EDUI_NAMESPACE_END
